﻿using System;
using System.Collections;
using System.IO;
using System.Web.Mvc;

using Blog.TemplateEngine;
using Blog.TemplateViewEngine.Filters;
using Blog.TemplateViewEngine.Functions;

namespace Blog.TemplateViewEngine
{
	public class TemplateViewFactory : IViewEngine
	{
        readonly string mViewFolder = "views";
        readonly string mLayoutFolder = "layouts";
        readonly Engine mTemplateEngine;

		public TemplateViewFactory()
		{
            mTemplateEngine = new Engine(AppDomain.CurrentDomain.BaseDirectory);
            mTemplateEngine.RegisterFilter("encode", new EncodeFilter());
            mTemplateEngine.RegisterFunction("url", new UrlFunction());
            mTemplateEngine.RegisterFunction("render_partial", new RenderPartialFunction(this));
        }

		private Template ResolveLayoutTemplate(string layoutName)
		{
			Template layoutTemplate = null;

			if(!string.IsNullOrEmpty(layoutName))
			{
				string layoutPath = Path.Combine(Path.Combine(mViewFolder, mLayoutFolder), layoutName);

				if(!Path.HasExtension(layoutPath))
				{
					layoutPath += ".vm";
				}

                layoutTemplate = mTemplateEngine.CreateTemplateFromFile(layoutPath);
			}
			return layoutTemplate;
		}

		public Template ResolveViewTemplate(string controllerFolder, string viewName)
		{
			string viewPath = Path.Combine(mViewFolder, Path.Combine(controllerFolder, viewName));

			if(!Path.HasExtension(viewPath))
			{
				viewPath += ".vm";
			}

            return mTemplateEngine.CreateTemplateFromFile(viewPath);
		}

		public void RenderView(ViewContext viewContext)
		{
            TemplateView view = CreateView(viewContext, true);
            viewContext.HttpContext.Response.Output.Write(view.RenderView(viewContext));
		}

		public TemplateView CreateView(ViewContext viewContext, bool withLayout)
	    {
			string controllerName = (string)viewContext.RouteData.Values["controller"];
			string controllerFolder = controllerName;

            string masterName = viewContext.MasterName ?? controllerName;

			Template viewTemplate = ResolveViewTemplate(controllerFolder, viewContext.ViewName);
            Template masterTemplate = withLayout ? ResolveLayoutTemplate(masterName) : null;

	    	TemplateView view = new TemplateView(viewTemplate, masterTemplate);

			return view;
	    }

        public TemplateView CreatePartial(string template, ViewContext viewContext)
        {
            string controllerName = (string)viewContext.RouteData.Values["controller"];
            string controllerFolder = controllerName;

            Template viewTemplate = ResolveViewTemplate(controllerFolder, "_" + template);
            TemplateView view = new TemplateView(viewTemplate, null);

            return view;
        }
    }
}
